home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / music / eked-m1.zoo / src / vk.c < prev   
C/C++ Source or Header  |  1995-02-19  |  7KB  |  233 lines

  1. /*
  2.  *  EKED-M1 : Editor for Korg M1 synth; defs.h : virtual keyboard
  3.  *  Copyright (C) 1995 Steven M. Eker (Steven.Eker@brunel.ac.uk)
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. #include <stddef.h>
  21. #include <string.h>
  22. #include <gemfast.h>
  23. #include <aesbind.h>
  24. #include <vdibind.h>
  25. #include "gm/gem_man.h"
  26. #include "eked-m1.h"
  27. #include "defs.h"
  28. #include "types.h"
  29. #include "externs.h"
  30.  
  31. #define WHITE_WIDTH    9
  32. #define WHITE_LEN    (5 * char_h - 2)
  33. #define WHITE_M_TOP     (4 * char_h - 2)
  34. #define WHITE_M_BOT     (5 * char_h - 3)
  35. #define BLACK_WIDTH    5
  36. #define BLACK_LEN    (3 * char_h - 2)
  37. #define BLACK_M_TOP     (2 * char_h - 2)
  38. #define BLACK_M_BOT    (3 * char_h - 3)
  39. #define OCT_WIDTH    (7 * WHITE_WIDTH)
  40. #define MIDI_LOW_C    36
  41. #define MIDI_VEL1    64
  42. #define MIDI_VEL2    127
  43. #define MIDI_RVEL    64
  44.  
  45. typedef struct {
  46.   int left_edge;
  47.   int color;
  48. } KEY_POS;
  49.  
  50. static KEY_POS key[] = {
  51.   {0, WHITE}, {6, BLACK}, {9, WHITE}, {17, BLACK}, {18, WHITE}, {27, WHITE},
  52.   {33, BLACK}, {36, WHITE}, {43, BLACK}, {45, WHITE}, {53, BLACK}, {54, WHITE}
  53. };
  54.  
  55. static int vk_handle = -1;
  56. static selected = -1;
  57.  
  58. static void display(int x_pos, int y_pos, GRECT *clip, long usr_val);
  59. static int action(int handle, E_TYPE type, void *event,
  60.                   int x_pos, int y_pos, long usr_val);
  61. static int find_key(int x, int y);
  62. static void update_marker(int handle, int x_pos, int y_pos, int note);
  63.  
  64.  
  65. void vk_window()
  66. {
  67.   if(vk_handle < 0){
  68.     vk_handle = wm_open(NAME | CLOSER | MOVER,
  69.                         (GRECT *) 0, "Virtual Keyboard",
  70.                         5 * OCT_WIDTH + 1, 5 * char_h, 0, 0,
  71.                         &display, &action, 0L);
  72.     if(vk_handle < 0)
  73.       fm_alert(1, WINDOW_ALERT);
  74.   }
  75.   else
  76.     wm_topped(vk_handle);
  77. }
  78.  
  79. static void display(int x_pos, int y_pos, GRECT *clip, long usr_val)
  80. {
  81.   int point[4];
  82.   int i, j, e, x;
  83.   int black_len = BLACK_LEN, white_len = WHITE_LEN;
  84.  
  85.   GM_AES2VDI(point, clip);
  86.   vs_clip(shared_handle, 1, point);
  87.   vsf_color(shared_handle, WHITE);
  88.   vr_recfl(shared_handle, point);
  89.   vsf_color(shared_handle, BLACK);
  90.  
  91.   i = (point[0] - x_pos) / OCT_WIDTH;
  92.   e = (point[2] - x_pos) / OCT_WIDTH;
  93.   if(e == 5){    /* right most edge */
  94.     point[0] = point[2];
  95.     point[1] = y_pos + 1;
  96.     point[3] = y_pos + white_len;
  97.     vr_recfl(shared_handle, point);
  98.     e = 4;
  99.   }
  100.   for(x = x_pos + i * OCT_WIDTH; i <= e; i++, x += OCT_WIDTH){
  101.     for(j = 0; j < 12; j++){
  102.       point[1] = y_pos + 1;
  103.       point[0] = x + key[j].left_edge;
  104.       if(key[j].color == WHITE){
  105.         point[2] = point[0];
  106.         point[3] = y_pos + white_len;
  107.         if(j != 0 && j != 5)
  108.           point[1] += black_len;
  109.       }
  110.       else{
  111.         point[2] = point[0] + BLACK_WIDTH - 1;
  112.         point[3] = y_pos + black_len;
  113.       }
  114.       vr_recfl(shared_handle, point);
  115.     }
  116.   }
  117.   point[0] = x_pos;
  118.   point[2] = x_pos + 5 * OCT_WIDTH;
  119.   point[1] = point[3] = y_pos;
  120.   vr_recfl(shared_handle, point);
  121.   point[1] = point[3] = y_pos + white_len + 1;
  122.   vr_recfl(shared_handle, point);
  123.  
  124.   if(selected >= 0){
  125.     i = selected % 12;
  126.     x = x_pos + OCT_WIDTH * (selected / 12);
  127.     if(key[i].color == WHITE){
  128.       point[0] = x + key[i].left_edge + 2;
  129.       point[2] = point[0] + WHITE_WIDTH - 4;
  130.       point[1] = y_pos + WHITE_M_TOP;
  131.       point[3] = y_pos + WHITE_M_BOT;
  132.       vr_recfl(shared_handle, point);
  133.     }
  134.     else{
  135.       point[0] = x + key[i].left_edge + 1;
  136.       point[2] = point[0] + BLACK_WIDTH - 3;
  137.       point[1] = y_pos + BLACK_M_TOP;
  138.       point[3] = y_pos + BLACK_M_BOT;
  139.       vsf_color(shared_handle, WHITE);
  140.       vr_recfl(shared_handle, point);
  141.     }
  142.   }
  143. }
  144.  
  145. static int action(int handle, E_TYPE type, void *event,
  146.                   int x_pos, int y_pos, long usr_val)
  147. {
  148.   int new, old, m_x, m_y, m_state, k_state;
  149.  
  150.   switch(type){
  151.   case E_CLEANUP:
  152.     vk_handle = -1;
  153.     break;
  154.   case E_CLICK:
  155.     wind_update(BEG_MCTRL);
  156.     do{
  157.       graf_mkstate(&m_x, &m_y, &m_state, &k_state);
  158.       new = m_state == 0 ? NIL : find_key(m_x - x_pos, m_y - y_pos);
  159.       old = selected;
  160.       if(new != old){
  161.         selected = new;
  162.         if(old != NIL){
  163.           tx_note_off(MIDI_LOW_C + old, MIDI_RVEL);
  164.           update_marker(handle, x_pos, y_pos, old);
  165.         }
  166.         if(new != NIL){
  167.           tx_note_on(MIDI_LOW_C + new, (k_state & 3) ? MIDI_VEL2 : MIDI_VEL1);
  168.           update_marker(handle, x_pos, y_pos, new);
  169.         }
  170.       }
  171.     }while(m_state != 0 || k_state != 0);
  172.     wind_update(END_MCTRL);
  173.     break;
  174.   }
  175.   return R_NORMAL;
  176. }
  177.  
  178. static int find_key(int x, int y)
  179. {
  180.   static white_map[] = {0, 2, 4, 5, 7, 9, 11};
  181.   int i, oct;
  182.  
  183.   if(y <= 0 || y > WHITE_LEN || x <= 0 || x >= 5 * OCT_WIDTH)
  184.     return NIL;
  185.   oct = x / OCT_WIDTH;
  186.   x = x % OCT_WIDTH;
  187.  
  188.   if(y > BLACK_LEN){
  189.     i = x / WHITE_WIDTH;
  190.     if(x % WHITE_WIDTH != 0)
  191.       return 12 * oct + white_map[i];
  192.   }
  193.   else{
  194.     for(i = 11; i >= 0; i--){
  195.       if(x >= key[i].left_edge){
  196.         if(key[i].color == WHITE){
  197.           if(i == 0 || i == 5){
  198.             if(x == key[i].left_edge)    /* B->C or E->F edge */
  199.               break;
  200.           }
  201.           else{
  202.             if(key[i - 1].left_edge + BLACK_WIDTH - 1 >= x)
  203.               i--;    /* black note actually covers part of D, E, G, A, B */
  204.           }
  205.         }
  206.         return 12 * oct + i;
  207.       }
  208.     }
  209.   }
  210.   return NIL;
  211. }
  212.  
  213. static void update_marker(int handle, int x_pos, int y_pos, int note)
  214. {
  215.   GRECT area;
  216.  
  217.   area.g_x = x_pos + OCT_WIDTH * (note / 12);
  218.   note %= 12;
  219.   if(key[note].color == WHITE){
  220.     area.g_x += key[note].left_edge + 2;
  221.     area.g_w = WHITE_WIDTH - 3;
  222.     area.g_y = y_pos + WHITE_M_TOP;
  223.     area.g_h = WHITE_M_BOT - WHITE_M_TOP + 1;
  224.   }
  225.   else{
  226.     area.g_x += key[note].left_edge + 1;
  227.     area.g_w = BLACK_WIDTH - 2;
  228.     area.g_y = y_pos + BLACK_M_TOP;
  229.     area.g_h = BLACK_M_BOT - BLACK_M_TOP + 1;
  230.   }
  231.   wm_redraw(handle, &area);
  232. }
  233.